package pattern.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import pattern.WorkServiceTool;
import pattern.annontations.Menu;
import pattern.annontations.Secure;
import pattern.config.session.SystemCacheManage;
import pattern.constant.CacheKeyConstant;
import pattern.dto.Role;
import pattern.dto.RoleOfDept;
import pattern.dto.model.system.*;
import pattern.i18n.I18nMessage;
import pattern.model.BaseIdModel;
import pattern.result.ResponseData;
import pattern.result.ResponsePage;
import pattern.result.ResponseResultStatus;
import pattern.routing.WorkMainApiRouting;
import pattern.utils.CollectionUtil;
import pattern.utils.SpringTool;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author Simon
 * @date 2020-08-21
 */
@Api(tags = "权限管理")
@RestController
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@Secure
@Slf4j
@RequestMapping(WorkMainApiRouting.Secure.BASE)
public class SecureController {

    @ApiOperation(value = "获取所有角色", tags = "角色管理")
    @GetMapping(WorkMainApiRouting.Secure.LIST)
    @Menu(verify = false, menuUri = "role", menuName = "role")
    @Secure(actionNote = "role", actionName = "search_all", actionUri = "all_role")
    public ResponsePage<Role> list(RoleListModel model) {
        return WorkServiceTool.getRoleService().page(model);
    }

    @ApiOperation(value = "详情", tags = "角色管理")
    @GetMapping(WorkMainApiRouting.Secure.DETAIL)
    @Secure(actionUri = "role:search", actionName = "search", actionNote = "role")
    public ResponseData<Role> detail(@PathVariable Integer id) {
        return new ResponseData<>(WorkServiceTool.getRoleService().getById(new BaseIdModel<>(id)));
    }

    @ApiOperation(value = "修改状态", tags = "角色管理")
    @PutMapping(WorkMainApiRouting.Secure.EDIT_STATUS)
    @Secure(actionUri = "add_or_update_role")
    public ResponseData<Boolean> editStatus(@RequestBody Role role) {
        return WorkServiceTool.getRoleService().updateStatus(new BaseIdModel<>(role));
    }

    @ApiOperation(value = "新增|修改角色", tags = "角色管理")
    @PostMapping(WorkMainApiRouting.Secure.SAVE_EDIT)
    @Menu(verify = false, menuName = "role")
    @Secure(actionNote = "role", actionName = "add_edit", actionUri = "add_or_update_role")
    public ResponseData<Boolean> editRole(@RequestBody RoleAddOrUpdateModel roleAddOrUpdateModel) {
        Integer roleId = (Integer) WorkServiceTool.getRoleService().saveOrUpdate(roleAddOrUpdateModel);
        SecureAddOrUpdateModel model = new SecureAddOrUpdateModel();
        model.setRoleId(roleId);
        model.setMenuIds(roleAddOrUpdateModel.getMenuIds().stream().filter(e -> e < 10000).collect(Collectors.toList()));
        model.setActionIds(roleAddOrUpdateModel.getMenuIds().stream().filter(e -> e >= 10000).collect(Collectors.toList()));
        return this.edit(model);
    }

    @ApiOperation(value = "删除角色", tags = "角色管理")
    @DeleteMapping(WorkMainApiRouting.Secure.DELETE)
    @Menu(verify = false, menuName = "role")
    @Secure(actionNote = "role", actionName = "delete", actionUri = "delete_role")
    public ResponseData<Boolean> delete(@PathVariable Integer id) {
        if (Objects.isNull(id)) {
            return new ResponseData<>(ResponseResultStatus.NULL_PARAM);
        }
        boolean flag = WorkServiceTool.getRoleService().removeRole(new BaseIdModel<>(id));
        SpringTool.getBean(SystemCacheManage.class).refresh();
        return new ResponseData<>(flag);
    }

    @ApiOperation("编辑角色人员")
    @PostMapping(WorkMainApiRouting.Secure.EDIT_ROLE_USER)
    @Menu(verify = false, menuName = "role")
    @Secure(actionNote = "role", actionName = "add_edit", actionUri = "role_user")
    public ResponseData permissionsEdit(@RequestBody RoleOfWorkerAddOrUpdateModel model) {
        if (Objects.isNull(model.getRoleId())) {
            return new ResponseData(ResponseResultStatus.NULL_PARAM);
        }
        boolean edit = WorkServiceTool.getUserOfRoleService().edit(model);
        return new ResponseData(edit);
    }

    @ApiOperation("角色权限信息")
    @GetMapping(WorkMainApiRouting.Secure.ROLE_INFO)
    @Menu(verify = false, menuName = "role")
    @Secure(actionNote = "role", actionName = "role_sec", actionUri = "role_info")
    public ResponseData roleInfo(@PathVariable Integer id) {
        Role role = WorkServiceTool.getRoleService().getById(new BaseIdModel<>(id));
        if (role == null) {
            return new ResponseData<>(ResponseResultStatus.NON_EXISTENT);
        }
        Map<String, Object> data = Maps.newHashMap();
        data.put("menus", this.all().getData());
        // 当前角色拥有的菜单,操作
        data.put("checkedKeys", CollectionUtil.addAll(WorkServiceTool.getMenuOfRoleService().getPermissionsOfRole(new BaseIdModel<>(id)), WorkServiceTool.getActionOfRoleService().getPermissionsOfRole(new BaseIdModel<>(id))));
        return new ResponseData<>(data);
    }


    @ApiOperation("所有权限信息")
    @GetMapping(WorkMainApiRouting.Secure.ALL)
    @Menu(verify = false, menuUri = "secure", menuName = "secure")
    @Secure(actionNote = "secure", actionName = "all_role", actionUri = "secure:dict")
    public ResponseData<List<Map<String, Object>>> all() {
        // 所有菜单,操作
        List<Map<String, Object>> result = Lists.newArrayList();
        var menus = WorkServiceTool.getCache().menuCache.get(CacheKeyConstant.UserKey.MENU_KEY);
        var actions = WorkServiceTool.getCache().actionCache.get(CacheKeyConstant.UserKey.ACTION_KEY);
        for (pattern.dto.Menu menu : menus) {
            Map<String, Object> map = Maps.newHashMap();
            map.put("label", I18nMessage.getMessage(menu.getMenuName()));
            map.put("id", menu.getId());
            var sonActions = actions.stream().filter(e -> e.getMenuGroup().equals(menu.getMenuName())).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(sonActions)) {
                List<Map<String, Object>> sonList = Lists.newArrayList();
                sonActions.forEach(e -> {
                    Map<String, Object> sonMap = Maps.newHashMap();
                    sonMap.put("label", I18nMessage.getMessage(e.getActionName()));
                    sonMap.put("id", e.getId());
                    sonList.add(sonMap);
                });
                map.put("children", sonList);
            }
            result.add(map);
        }
        return new ResponseData<>(result);
    }


    @ApiOperation("编辑角色权限信息")
    @PostMapping(WorkMainApiRouting.Secure.EDIT)
    @Menu(verify = false, menuName = "secure")
    @Secure(actionNote = "secure", actionName = "add_edit", actionUri = "secure:edit")
    public ResponseData<Boolean> edit(@RequestBody SecureAddOrUpdateModel model) {
        if (Objects.isNull(model.getRoleId())) {
            return new ResponseData<>(ResponseResultStatus.NULL_PARAM);
        }
        boolean edit = WorkServiceTool.getMenuOfRoleService().edit(model);
        boolean edit1 = WorkServiceTool.getActionOfRoleService().edit(model);
        SpringTool.getBean(SystemCacheManage.class).refresh();
        SpringTool.getBean(SystemCacheManage.class).deptUserRefresh();
        return new ResponseData<>(edit && edit1);
    }

    @ApiOperation("编辑权限")
    @PutMapping(WorkMainApiRouting.Secure.DATA_SCOPE)
    @Menu(verify = false, menuName = "secure")
    @Secure(actionNote = "secure", actionName = "add_edit", actionUri = "secure:edit")
    public ResponseData<Boolean> dataScope(@RequestBody RoleDeptEditModel model) {
        if (StringUtils.isNotBlank(model.getDataScope())) {
            WorkServiceTool.getRoleService().getBaseMapper().updateById(model.toBean());
        }
        if (CollectionUtil.isNotEmpty(model.getDeptIds())) {
            var roleOfDepts = model.getDeptIds().stream().map(e -> new RoleOfDept().setDeptId(e).setRoleId(model.getId())).collect(Collectors.toList());
            WorkServiceTool.getRoleOfDeptService().getBaseMapper().delete(new LambdaQueryWrapper<RoleOfDept>().eq(RoleOfDept::getRoleId, model.getId()));
            WorkServiceTool.getRoleOfDeptService().saveBatch(roleOfDepts);
        }
        SpringTool.getBean(SystemCacheManage.class).deptUserRefresh();
        return new ResponseData<>(Boolean.TRUE);
    }

}
